# -*- coding: utf-8 -*-
# @Time    : 2024/6/21 17:52
# @Author  : yujiahao
# @File    : 04_pandas_descriptive_statistics.py
# @description:Python Pandas描述性统计

"""
描述统计学（descriptive statistics）是一门统计学领域的学科，主要研究如何取得反映客观现象的数据，
并以图表形式对所搜集的数据进行处理和显示，最终对数据的规律、特征做出综合性的描述分析。
Pandas 库正是对描述统计学知识完美应用的体现，可以说如果没有“描述统计学”作为理论基奠，
那么 Pandas 是否存在犹未可知。

下列表格对 Pandas 常用的统计学函数做了简单的总结：


    +-----------+---------------------------------------------------------------+
    | 函数名称  | 描述说明
    +-----------+---------------------------------------------------------------+
    | count()   | 统计某个非空值的数量。
    | sum()     | 求和。
    | mean()    | 求均值。
    | median()  | 求中位数。中位数是排序后位于中间的值。例如，[1, 3, 3, 6, 7, 8, 9] 的中位数是 6。
    | mode()    | 求众数。众数是出现次数最多的值。例如，[1, 2, 2, 3, 4] 的众数是 2。
    | std()     | 求标准差。标准差是数据平均值分散程度的一种度量。
    | min()     | 求最小值。
    | max()     | 求最大值。
    | abs()     | 求绝对值。
    | prod()    | 求所有数值的乘积。
    | cumsum()  | 计算累计和，axis=0，按照行累加；axis=1，按照列累加。
    | cumprod() | 计算累计积，axis=0，按照行累积；axis=1，按照列累积。
    | corr()    | 计算数列或变量之间的相关系数，取值范围为-1到1。值越接近1表示正相关性越强，值越接近-1表示负相关性越强。例如，两个完全正相关的变量相关系数为 1。
    +-----------+---------------------------------------------------------------+


从描述统计学角度出发，我们可以对 DataFrame 结构执行聚合计算等其他操作，比如 sum() 求和、mean()求均值等方法。

在 DataFrame 中，使用聚合类方法时需要指定轴(axis)参数。下面介绍两种传参方式：

    1. 对行操作，默认使用 axis=0 或者使用 "index"；
    2. 对列操作，默认使用 axis=1 或者使用 "columns"。

axis轴示意图：

    图1：axis轴示意图
    +-----+-----+-----+-----+
    |     |  A  |  B  |  C  |       \
    +-----+-----+-----+-----+       \
    |  0  |  1  |  2  |  3  |       |
    +-----+-----+-----+-----+       \|
    |  1  |  4  |  5  |  6  |        X = 0 向下
    +-----+-----+-----+-----+
    |  2  |  7  |  8  |  9  |
    +-----+-----+-----+-----+
            -------> x = 1


从图 1 可以看出，axis=0 表示按垂直方向进行计算，而 axis=1 则表示按水平方向。

下面让我们创建一个 DataFrame，使用它对本节的内容进行演示。
"""
import pandas as pd


class DataFrameDescriptiveStatistics:
    def __init__(self):
        self.df = self.create_df()

    def create_df(self):
        # 创建字典型series结构
        d = {
            'Name': pd.Series(['小明', '小亮', '小红', '小华', '老赵', '小曹', '小陈',
                               '老李', '老王', '小冯', '小何', '老张']),
            'Age': pd.Series([25, 26, 25, 23, 30, 29, 23, 34, 40, 30, 51, 46]),
            'Rating': pd.Series([4.23, 3.24, 3.98, 2.56, 3.20, 4.6, 3.8, 3.78, 2.98, 4.80, 4.10, 3.65])
        }
        df = pd.DataFrame(d)
        return df

    def display_statistics(self):
        print("原始 DataFrame:")
        print(self.df)
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # count() 统计非空值的数量
        print("count():")
        print(self.df.count())
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # sum() 求和
        print("sum():")
        print(self.df.sum(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # mean() 求均值
        print("mean():")
        print(self.df.mean(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # median() 求中位数
        print("median():")
        print(self.df.median(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # mode() 求众数
        print("mode():")
        print(self.df.mode())
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # std() 求标准差
        print("std():")
        print(self.df.std(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # min() 求最小值
        print("min():")
        print(self.df.min(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # max() 求最大值
        print("max():")
        print(self.df.max(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # abs() 求绝对值，只选择数值列
        print("abs():")
        print(self.df.select_dtypes(include=[float, int]).abs())
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # prod() 求所有数值的乘积
        print("prod():")
        print(self.df.prod(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # cumsum() 计算累计和
        print("cumsum() 按行累加:")
        print(self.df.select_dtypes(include=[float, int]).cumsum(axis=0))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')
        print("cumsum() 按列累加:")
        print(self.df.select_dtypes(include=[float, int]).cumsum(axis=1))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # cumprod() 计算累计积
        print("cumprod() 按行累积:")
        print(self.df.select_dtypes(include=[float, int]).cumprod(axis=0))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')
        print("cumprod() 按列累积:")
        print(self.df.select_dtypes(include=[float, int]).cumprod(axis=1))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

        # corr() 计算相关系数
        print("corr():")
        print(self.df.corr(numeric_only=True))
        print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')


def main():
    stats = DataFrameDescriptiveStatistics()
    stats.display_statistics()


if __name__ == '__main__':
    main()
